"""
话术功能模块，包含话术相关的UI和功能
"""
import os
import random
import time
from PyQt5.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QGroupBox, QLabel,
    QPushButton, QTableWidget, QTableWidgetItem, QHeaderView, QComboBox, QDialog, QTextEdit, QMessageBox, QLineEdit
)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QBrush, QColor

from app.ui.components.styled_button import StyledButton
from app.ui.components.styled_label import StyledLabel
from app.utils.logger import Logger
from app.services.service_locator import ServiceLocator
from app.services.config_service import IConfigService

class SpeechModule(QWidget):
    """
    话术功能模块类，包含话术相关的UI和功能
    """
    
    # 定义信号
    speech_updated = pyqtSignal(str, object)  # 话术更新信号
    
    def __init__(self, parent=None):
        """
        初始化话术功能模块
        """
        super().__init__(parent)
        
        # 获取日志记录器
        self.logger = Logger.get_logger("speech_module")
        
        # 初始化成员变量
        self.speech_table = None
        self.speech_type_combo = None
        self.config_path = None
        
        # 获取配置服务
        self.config_service = ServiceLocator.get(IConfigService)
        if self.config_service:
            self.config_path = self.config_service.get("app.config_path", "")
        
        # 初始化UI
        self._init_ui()
    
    def _init_ui(self):
        """
        初始化UI
        """
        # 创建主布局
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(10)
        
        # 创建标题
        title_label = StyledLabel("话术管理", size=StyledLabel.LARGE, bold=True)
        main_layout.addWidget(title_label)
        
        # 创建话术配置组
        self._create_speech_config_group(main_layout)
        
        # 加载话术类型
        self._load_speech_types()
    
    def _load_speech_types(self):
        """
        从配置路径的话术管理目录中加载话术类型
        """
        if not self.config_path:
            self.logger.warning("配置路径未设置，无法加载话术类型")
            return
        
        # 构建话术管理目录路径
        speech_dir = os.path.join(self.config_path, "话术管理")
        
        # 检查目录是否存在
        if not os.path.exists(speech_dir):
            self.logger.info(f"话术管理目录不存在，创建目录: {speech_dir}")
            try:
                os.makedirs(speech_dir, exist_ok=True)
            except Exception as e:
                self.logger.error(f"创建话术管理目录失败: {str(e)}")
                return
                
        # 创建必需的话术目录
        required_folders = {
            "关键词话术": ["已拍@拍了.txt","不会@怎么找@找不到@教一下.txt"],
            "欢迎话术": ["低速.txt", "中速.txt", "高速.txt"],
            "主话术": ["1.txt", "2.txt", "3.txt", "4.txt", "5.txt", "6.txt", "7.txt", "8.txt", "9.txt", "10.txt"]
        }
        
        for folder, files in required_folders.items():
            folder_path = os.path.join(speech_dir, folder)
            if not os.path.exists(folder_path):
                self.logger.info(f"创建话术目录: {folder}")
                try:
                    os.makedirs(folder_path, exist_ok=True)
                    # 创建必需的文件
                    for file in files:
                        file_path = os.path.join(folder_path, file)
                        if not os.path.exists(file_path):
                            self.logger.info(f"创建话术文件: {file}")
                            with open(file_path, "w", encoding="utf-8") as f:
                                pass
                except Exception as e:
                    self.logger.error(f"创建话术目录或文件失败: {str(e)}")
                    continue
        
        # 完全清空下拉框
        self.speech_type_combo.clear()
        
        # 获取目录中的文件夹
        try:
            folders = [f for f in os.listdir(speech_dir) if os.path.isdir(os.path.join(speech_dir, f))]
            
            # 添加文件夹到下拉框
            for folder in folders:
                self.speech_type_combo.addItem(folder)
                
            self.logger.info(f"已加载 {len(folders)} 个话术类型")
            
            # 如果有话术类型，自动选择第一个
            if self.speech_type_combo.count() > 0:
                self.speech_type_combo.setCurrentIndex(0)
        except Exception as e:
            self.logger.error(f"加载话术类型失败: {str(e)}")
    
    def _on_speech_type_changed(self, index):
        """
        话术类型选择变化事件处理
        
        @param index: 选中的索引
        """
        if index < 0:
            self.logger.info("未选择有效的话术类型")
            return
        
        speech_type = self.speech_type_combo.currentText()
        self.logger.info(f"选择话术类型: {speech_type}")
        
        # 加载该类型的话术
        self._load_speeches(speech_type)
    
    def _load_speeches(self, speech_type):
        """
        加载指定类型的话术
        
        @param speech_type: 话术类型
        """
        if not self.config_path:
            self.logger.warning("配置路径未设置，无法加载话术")
            return
        
        # 构建话术目录路径
        speech_dir = os.path.join(self.config_path, "话术管理", speech_type)
        
        # 检查目录是否存在
        if not os.path.exists(speech_dir):
            self.logger.warning(f"话术目录不存在: {speech_dir}")
            return
        
        # 清空话术表格
        self.speech_table.setRowCount(0)
        
        # 获取目录中的文本文件
        try:
            files = [f for f in os.listdir(speech_dir) if f.endswith('.txt')]
            
            # 按照n.n-文件名.txt格式排序
            def get_sort_key(filename):
                """
                从文件名中提取排序键
                支持以下格式：
                1. 纯数字格式：1.0.txt
                2. 带花括号的格式：3.0{停顿}.txt
                3. 带后缀的格式：6.1人数时间.txt
                """
                try:
                    # 提取文件名中的数字部分
                    import re
                    # 匹配文件名开头的数字部分（如1.0, 3.0, 6.1等）
                    match = re.match(r'^(\d+\.\d+)', filename)
                    if match:
                        return float(match.group(1))
                except (ValueError, IndexError, AttributeError):
                    pass
                # 如果无法提取排序键，则返回一个很大的数，使其排在最后
                return float('inf')
            
            # 按照排序键排序
            sorted_files = sorted(files, key=get_sort_key)
            
            for file in sorted_files:
                file_path = os.path.join(speech_dir, file)
                # 直接添加文件名到列表中，而不是读取内容
                self._add_speech_item(file, file_path)
            
            self.logger.info(f"已加载 {len(files)} 个话术")
            
            # 如果没有话术，添加提示信息
            if len(files) == 0:
                self.speech_table.setRowCount(1)
                info_item = QTableWidgetItem("当前文件夹没有话术文件，请添加.txt文件")
                info_item.setForeground(QBrush(QColor(150, 150, 150)))
                self.speech_table.setItem(0, 0, info_item)
                self.speech_table.setSpan(0, 0, 1, 2)  # 合并单元格
        except Exception as e:
            self.logger.error(f"加载话术失败: {str(e)}")
    
    def _create_speech_config_group(self, parent_layout):
        """
        创建话术配置组
        
        @param parent_layout: 父布局
        """
        # 创建话术类型选择布局
        top_layout = QHBoxLayout()
        
        # 创建话术类型下拉框
        self.speech_type_combo = QComboBox()
        self.speech_type_combo.setMinimumHeight(30)
        self.speech_type_combo.currentIndexChanged.connect(self._on_speech_type_changed)
        top_layout.addWidget(self.speech_type_combo, 1)  # 1是伸展因子
        
        # 添加新话术按钮
        add_btn = StyledButton("添加话术")
        add_btn.setMinimumWidth(120)
        add_btn.clicked.connect(self._add_speech)
        top_layout.addWidget(add_btn)
        
        parent_layout.addLayout(top_layout)
        
        # 创建话术表格
        self.speech_table = QTableWidget()
        self.speech_table.setColumnCount(2)
        self.speech_table.setHorizontalHeaderLabels(["话术文件", "操作"])
        self.speech_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
        self.speech_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.speech_table.verticalHeader().setVisible(False)
        self.speech_table.setAlternatingRowColors(True)
        # 设置行高
        self.speech_table.verticalHeader().setDefaultSectionSize(28)
        # 禁止编辑
        self.speech_table.setEditTriggers(QTableWidget.NoEditTriggers)
        
        parent_layout.addWidget(self.speech_table, 1)  # 1是伸展因子
    
    def _add_speech_item(self, content, file_path):
        """
        添加话术项目
        
        @param content: 话术内容或文件名
        @param file_path: 话术文件路径
        """
        row = self.speech_table.rowCount()
        self.speech_table.insertRow(row)
        
        # 添加话术内容
        display_content = content
        # 如果内容太长，截断显示
        if len(display_content) > 50:
            display_content = display_content[:47] + "..."
        
        content_item = QTableWidgetItem(display_content)
        # 设置完整内容为工具提示
        content_item.setToolTip(content)
        self.speech_table.setItem(row, 0, content_item)
        
        # 添加打开按钮
        open_btn = StyledButton("打开")
        open_btn.setFixedWidth(60)
        
        # 为打开按钮单独设置样式，减小padding并缩小文字大小
        open_btn.setStyleSheet("""
            QPushButton {
                padding: 0px;
                font-size: 12px;
                font-weight: bold;
                color: #333333;
            }
            QPushButton:hover {
                background-color: #e6e6e6;
                border-color: #ccc;
            }
            QPushButton:pressed {
                background-color: #d9d9d9;
            }
        """)
        
        open_btn.clicked.connect(lambda: self._on_open_clicked(file_path))
        self.speech_table.setCellWidget(row, 1, open_btn)
    
    def _on_open_clicked(self, file_path):
        """
        打开按钮点击事件处理
        
        @param file_path: 文件路径
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(file_path):
                QMessageBox.warning(self, "警告", f"文件不存在: {file_path}")
                return
            
            # 使用系统默认程序打开文件
            self.logger.info(f"正在打开文件: {file_path}")
            
            # 根据操作系统选择打开方式
            import platform
            import subprocess
            
            system = platform.system()
            
            if system == 'Windows':
                os.startfile(file_path)
            elif system == 'Darwin':  # macOS
                subprocess.call(('open', file_path))
            else:  # Linux
                subprocess.call(('xdg-open', file_path))
                
            self.logger.info(f"已打开文件: {file_path}")
        except Exception as e:
            self.logger.error(f"打开文件失败: {str(e)}")
            import traceback
            traceback.print_exc()
            QMessageBox.critical(self, "错误", f"打开文件失败: {str(e)}")
    
    def _play_audio(self, file_path):
        """
        播放音频
        
        @param file_path: 音频文件路径
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(file_path):
                QMessageBox.warning(self, "警告", f"音频文件不存在: {file_path}")
                return
                
            # 获取音频服务
            from app.services.audio_service import IAudioService
            audio_service = ServiceLocator.get(IAudioService)
            
            if not audio_service:
                QMessageBox.warning(self, "警告", "无法获取音频服务")
                return
            
            # 播放音频
            audio_service.play(file_path)
            self.logger.info(f"正在播放音频: {file_path}")
        except Exception as e:
            self.logger.error(f"播放音频失败: {str(e)}")
            import traceback
            traceback.print_exc()
            QMessageBox.warning(self, "警告", f"播放音频失败: {str(e)}")
    
    def _add_speech(self):
        """
        添加话术
        """
        if not self.config_path:
            QMessageBox.warning(self, "警告", "请先设置配置路径")
            return
            
        speech_type = self.speech_type_combo.currentText()
        if not speech_type:
            QMessageBox.warning(self, "警告", "请先选择话术类型")
            return
            
        # 创建对话框
        dialog = QDialog(self)
        dialog.setWindowTitle("添加话术")
        dialog.setMinimumSize(500, 400)
        
        # 禁用ESC键关闭对话框
        dialog.setWindowFlags(dialog.windowFlags() & ~Qt.WindowContextHelpButtonHint)
        
        # 创建布局
        layout = QVBoxLayout(dialog)
        
        # 创建文件名输入框
        filename_layout = QHBoxLayout()
        filename_label = QLabel("文件名:")
        filename_layout.addWidget(filename_label)
        
        filename_input = QLineEdit()
        filename_input.setPlaceholderText("请输入文件名（不含.txt后缀）")
        filename_layout.addWidget(filename_input)
        
        layout.addLayout(filename_layout)
        
        # 创建内容输入框
        content_label = QLabel("话术内容:")
        layout.addWidget(content_label)
        
        content_edit = QTextEdit()
        layout.addWidget(content_edit, 1)  # 增加拉伸因子，使输入框占用更多空间
        
        # 创建替换规则说明
        rules_label = QLabel("替换规则快速插入:")
        layout.addWidget(rules_label)
        
        # 创建替换规则按钮布局（不使用分组）
        rules_layout = QVBoxLayout()
        
        # 设置替换规则按钮的样式
        rule_button_style = """
            QPushButton {
                padding: 6px 12px;
                border: 1px solid #ddd;
                border-radius: 4px;
                background-color: #f8f9fa;
            }
            QPushButton:hover {
                background-color: #e9ecef;
                border-color: #ced4da;
            }
            QPushButton:pressed {
                background-color: #dee2e6;
            }
        """
        
        # 时间日期变量
        time_vars_layout = QHBoxLayout()
        
        time_btn = QPushButton("当前时间")
        time_btn.setStyleSheet(rule_button_style)
        time_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{当前时间}"))
        time_vars_layout.addWidget(time_btn)
        
        date_btn = QPushButton("当前日期")
        date_btn.setStyleSheet(rule_button_style)
        date_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{当前日期}"))
        time_vars_layout.addWidget(date_btn)
        
        weekday_btn = QPushButton("星期")
        weekday_btn.setStyleSheet(rule_button_style)
        weekday_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{星期}"))
        time_vars_layout.addWidget(weekday_btn)
        
        year_btn = QPushButton("年")
        year_btn.setStyleSheet(rule_button_style)
        year_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{当前年}"))
        time_vars_layout.addWidget(year_btn)
        
        month_btn = QPushButton("月")
        month_btn.setStyleSheet(rule_button_style)
        month_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{当前月}"))
        time_vars_layout.addWidget(month_btn)
        
        day_btn = QPushButton("日")
        day_btn.setStyleSheet(rule_button_style)
        day_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{当前日}"))
        time_vars_layout.addWidget(day_btn)
        
        rules_layout.addLayout(time_vars_layout)
        
        # 用户变量
        user_vars_layout = QHBoxLayout()
        
        username_btn = QPushButton("用户名")
        username_btn.setStyleSheet(rule_button_style)
        username_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{用户名}"))
        user_vars_layout.addWidget(username_btn)
        
        viewer_count_btn = QPushButton("观众数量")
        viewer_count_btn.setStyleSheet(rule_button_style)
        viewer_count_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{观众数量}"))
        user_vars_layout.addWidget(viewer_count_btn)
        
        gift_name_btn = QPushButton("礼物名称")
        gift_name_btn.setStyleSheet(rule_button_style)
        gift_name_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{礼物名称}"))
        user_vars_layout.addWidget(gift_name_btn)
        
        gift_count_btn = QPushButton("礼物数量")
        gift_count_btn.setStyleSheet(rule_button_style)
        gift_count_btn.clicked.connect(lambda: self._insert_rule(content_edit, "{礼物数量}"))
        user_vars_layout.addWidget(gift_count_btn)
        
        rules_layout.addLayout(user_vars_layout)
        
        # 自定义随机文本
        custom_random_layout = QHBoxLayout()
        custom_random_label = QLabel("自定义随机文本:")
        custom_random_layout.addWidget(custom_random_label)
        
        custom_random_input = QLineEdit()
        custom_random_input.setPlaceholderText("输入选项，用|分隔")
        custom_random_layout.addWidget(custom_random_input)
        
        custom_random_btn = QPushButton("插入")
        custom_random_btn.setStyleSheet(rule_button_style)
        custom_random_btn.clicked.connect(lambda: self._insert_custom_random(content_edit, custom_random_input.text()))
        custom_random_layout.addWidget(custom_random_btn)
        
        rules_layout.addLayout(custom_random_layout)
        
        # 帮助提示
        help_text = QLabel("提示: 内置变量使用{变量名}格式，随机文本使用{选项1|选项2|选项3}格式")
        help_text.setStyleSheet("color: #F44336; font-size: 12px;")  # 使用红色显示提示文字
        rules_layout.addWidget(help_text)
        
        layout.addLayout(rules_layout)
        
        # 创建按钮布局
        btn_layout = QHBoxLayout()
        btn_layout.addStretch()
        
        # 创建保存按钮，使用StyledButton
        save_btn = StyledButton("保存", button_type=StyledButton.PRIMARY)
        save_btn.setMinimumHeight(36)  # 增加按钮高度
        save_btn.clicked.connect(lambda: self._save_new_speech(speech_type, filename_input.text(), content_edit.toPlainText(), dialog))
        btn_layout.addWidget(save_btn)
        
        # 创建取消按钮，使用StyledButton
        cancel_btn = StyledButton("取消", button_type=StyledButton.SECONDARY)
        cancel_btn.setMinimumHeight(36)  # 增加按钮高度
        cancel_btn.clicked.connect(dialog.reject)
        btn_layout.addWidget(cancel_btn)
        
        layout.addLayout(btn_layout)
        
        # 重写keyPressEvent方法，禁用ESC键关闭对话框
        def keyPressEvent(event):
            if event.key() != Qt.Key_Escape:  # 忽略ESC键
                super(QDialog, dialog).keyPressEvent(event)
        
        dialog.keyPressEvent = keyPressEvent
        
        # 显示对话框
        dialog.exec_()
    
    def _insert_rule(self, text_edit, rule):
        """
        在文本编辑器中插入规则
        
        @param text_edit: 文本编辑器
        @param rule: 要插入的规则
        """
        cursor = text_edit.textCursor()
        cursor.insertText(rule)
        text_edit.setFocus()
    
    def _insert_custom_random(self, text_edit, options_text):
        """
        插入自定义随机文本
        
        @param text_edit: 文本编辑器
        @param options_text: 选项文本，用|分隔
        """
        if not options_text:
            return
            
        # 格式化为{选项1|选项2|选项3}格式
        options = options_text.split('|')
        if len(options) < 2:
            QMessageBox.warning(self, "警告", "至少需要两个选项，用|分隔")
            return
            
        formatted_rule = "{" + options_text + "}"
        self._insert_rule(text_edit, formatted_rule)
    
    def _save_new_speech(self, speech_type, filename, content, dialog):
        """
        保存新话术
        
        @param speech_type: 话术类型
        @param filename: 文件名
        @param content: 话术内容
        @param dialog: 对话框
        """
        if not filename:
            QMessageBox.warning(dialog, "警告", "请输入文件名")
            return
            
        # 构建话术目录路径
        speech_dir = os.path.join(self.config_path, "话术管理", speech_type)
        
        # 检查目录是否存在，不存在则创建
        if not os.path.exists(speech_dir):
            os.makedirs(speech_dir)
            
        # 构建文件路径
        if not filename.endswith('.txt'):
            filename += '.txt'
            
        file_path = os.path.join(speech_dir, filename)
        
        # 检查文件是否已存在
        if os.path.exists(file_path):
            reply = QMessageBox.question(dialog, "确认", "文件已存在，是否覆盖？", 
                                        QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.No:
                return
                
        try:
            # 保存内容到文件
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(content)
                
            self.logger.info(f"已保存新话术: {file_path}")
            
            # 关闭对话框
            dialog.accept()
            
            # 重新加载话术列表
            self._load_speeches(speech_type)
            
        except Exception as e:
            self.logger.error(f"保存新话术失败: {str(e)}")
            QMessageBox.critical(dialog, "错误", f"保存新话术失败: {str(e)}")
    
    def set_config_path(self, path):
        """
        设置配置路径
        
        @param path: 配置路径
        """
        self.config_path = path
        self.logger.info(f"设置配置路径: {path}")
        
        # 重新加载话术类型
        self._load_speech_types() 